<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .wrap {
            width: 400px;
            transition: max-height .4s;
            max-height: 200px;
            overflow: hidden;
        }
        .wrap-max {
            max-height: 1000px;
        }
        .wrap div {
            height: 200px;
        }
        .box1 {
            background: #908aef;
        }
        .box2 {
            background: #908aef;
        }
        .box3 {
            background: #908aef;
        }
        .box4 {
            background: #908aef;
        }

        .last {
           display: none;
        }
        .bl {
            display: block;
        }
    </style>
</head>
<body>
<div>
    <button id="btn">展开</button>
    <div class="wrap">
        <div class="box1"></div>
        <div class="box2"></div>
        <section class="last">
            <div class="box3"></div>
            <div  class="box4"></div>
        </section>
    </div>
</div>
<script>
  // 这个方法有局限性，如果max-height太大，最终的视觉效果将看不到动画，而且频繁的切换也会有卡顿的感觉
  // max-height太大导致动画卡顿的原因是：动画作用于max-height变化的每一个阶段，当max-height太大时，
  // 元素增长到某一个高度需要的时间就会比max-height较小需要的时间更少，所以在较少的时间内完成了动画看起来
  // 就会有卡顿的感觉
    const btn = document.querySelector("#btn");
    const section = document.querySelector(".last");
    const wrap = document.querySelector(".wrap");
    let isExpand = false;

    btn.onclick = function () {
      if (!isExpand) {
        section.classList.add("bl")
        wrap.classList.add("wrap-max")
      } else {
        setTimeout(() => {
          section.classList.remove("bl")
        }, 400)
        wrap.classList.remove("wrap-max")
      }
      isExpand = !isExpand;
    }
</script>
</body>
</html>